home *** CD-ROM | disk | FTP | other *** search
- /*
- File: DialogUtils.cp
-
- Contains: Auto-sized error alert mechanism and ModalFilterProcs
- which correctly handle events.
-
- Written by: Dave Falkenburg
-
- Copyright: © 1993-1995 by Dave Falkenburg, all rights reserved.
-
- Change History (most recent first):
-
- <8> 1/20/95 DRF Gary Powell is a bug finding god. Fix an unitialized variable
- problem in ErrorAlert.
- <7> 1/3/95 DRF Gave UPPs better names. Also moved StandardCloseDocument to
- Document.h.
- <6> 11/23/94 DRF Add ToggleCheckBox, a nice little dialog item utility.
- <5> 11/16/94 DRF Added explicit #include <SegLoad.h> for latest universal
- headers. Also added cast to keep MPW CFront happier.
- <4> 11/16/94 DRF Add StdFilterProc for THINK C.
- <3> 9/27/94 DRF AppLib.h is now Sprocket.h
- <2> 9/9/94 DRF Reordered headers and removed redundant #includes.
- */
-
- #include "Sprocket.h"
-
- #include <Fonts.h>
- #include <Resources.h>
- #include <TextUtils.h>
- #include <Threads.h> // For YieldToAnyThread()
- #include <StandardFile.h> // For ModalFilterYDProcPtr
- #include <SegLoad.h> // For ExitToShell()
-
- // Some types which should probably be defined in <Dialogs.h>
- // NOTE: These must be aligned on 2-byte boundaries
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma push
- #pragma options align=mac68k
- #endif
-
- struct DialogItem
- {
- long usedByDialogManager;
- Rect boundsRect;
- char type;
- char length;
- };
-
- struct DialogItemList // a.k.a. a 'DITL'
- {
- short count;
- DialogItem firstItem[1];
- };
-
- // Restore default alignment
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma pop
- #endif
-
-
- typedef DialogItem *DialogItemPtr;
- typedef DialogItemList **DialogItemListHandle;
- typedef DialogTemplate **DialogTemplateHandle;
-
- /*
- #ifndef powerc
- #ifdef __SC__
-
- extern pascal OSErr GetStdFilterProc(ModalFilterUPP *theProc)
- THREEWORDINLINE(0x303C, 0x0203, 0xAA68);
-
- pascal Boolean
- StdFilterProc(DialogPtr theDialog, EventRecord* anEvent, short* itemHit)
- {
- ModalFilterUPP filterUPP;
-
- // Dialogs.h
-
- (void) GetStdFilterProc(&filterUPP);
-
- return CallModalFilterProc(filterUPP,theDialog,anEvent,itemHit);
- }
-
- #endif
- #endif
- */
-
- // private function Prototypes
-
- pascal Boolean StandardDialogFilterProc(DialogRef theDialog, EventRecord * anEvent, short * itemHit);
- static pascal Boolean StandardDialogFilterYDProc(DialogRef theDialog, EventRecord * anEvent, short * itemHit, void * yourData);
- static pascal Boolean StandardCloseDialogFilterProc(DialogRef theDialog, EventRecord * anEvent, short * itemHit);
- static Boolean FilterProcCommon(DialogRef theDialog, EventRecord * anEvent, short * itemHit);
-
-
-
- ///////////////////////////////////////////////////////////
- //
- // StandardAlert
- //
- // An alternative to Alert() which uses the extended
- // Dialog Manager capabilities.
- //
- // I’m not sure we really need this call, but it seems
- // to do the trick just fine.
-
- short
- StandardAlert( short dlogID,
- short defaultItem, /* = ok */
- short cancelItem, /* = 0 */
- ModalFilterUPP customFilterUPP /* = nil */)
- {
- DialogRef theDialog;
- short itemHit = 0;
- ModalFilterUPP filterToUse;
-
- TWindow::EnterModalState();
-
- theDialog = GetNewDialog(dlogID,nil,(WindowRef) -1);
- if (defaultItem)
- SetDialogDefaultItem(theDialog,defaultItem);
- if (cancelItem)
- SetDialogCancelItem(theDialog,cancelItem);
-
- if (customFilterUPP)
- filterToUse = customFilterUPP;
- else
- filterToUse = StandardDialogFilterUPP;
-
- do
- ModalDialog(filterToUse,&itemHit);
- while (itemHit == 0);
-
- DisposeDialog(theDialog);
-
- TWindow::ExitModalState();
-
- return itemHit;
- }
-
-
- ///////////////////////////////////////////////////////////
- //
- // ErrorAlert
- //
- // A nice error reporting routine which presents an
- // auto-sized alert box containing the supplied text.
- //
- // NOTE: This routine ASSUMES the following 'DITL'
- // structure:
- //
- // item #1 : an “OK” button
- // item #2 : a static text item, somewhere above #1
- //
- // NOTE: We probably need to worry more about low
- // memory conditions-- this can probably
- // be handled by a custom GrowZoneProc and
- // reserve memory area large enough to hold
- // all the space we’d need.
- //
-
- void
- ErrorAlert(short stringList,short whichString)
- {
- Str255 errorString;
- GrafPtr oldPort,windowMgrPort;
- short oldFont;
- DialogTemplateHandle errorDialogTemplate;
- DialogItemListHandle errorDialogItems;
- TEHandle aTEHandle;
- Rect textRect;
- short textHeight;
- short additionalSpaceNeeded;
- DialogItemPtr okButtonItem,errorTextItem;
- const StringPtr nullStr = (StringPtr) "\p";
-
- GetIndString(errorString,stringList,whichString);
-
- errorDialogTemplate = (DialogTemplateHandle) Get1Resource('DLOG',kErrorAlertID);
- HLock((Handle) errorDialogTemplate);
-
- errorDialogItems = (DialogItemListHandle) Get1Resource('DITL',(**errorDialogTemplate).itemsID);
- HLock((Handle) errorDialogItems);
-
- // Find the dialog items
-
- okButtonItem = (**errorDialogItems).firstItem;
- errorTextItem = (DialogItemPtr) ((Ptr) okButtonItem + sizeof(DialogItem) + okButtonItem->length);
-
- GetPort(&oldPort);
- GetWMgrPort(&windowMgrPort);
- SetPort(windowMgrPort);
- oldFont = qd.thePort->txFont;
- TextFont(systemFont);
-
- // use the initial size from the 'DITL', instead of random garbage.
- textRect = errorTextItem->boundsRect;
- aTEHandle = TENew(&textRect,&textRect);
- TESetText(&errorString[1],errorString[0],aTEHandle);
- textHeight = (*aTEHandle)->lineHeight * (*aTEHandle)->nLines;
- TEDispose(aTEHandle);
-
- additionalSpaceNeeded = textHeight - (errorTextItem->boundsRect.bottom
- - errorTextItem->boundsRect.top);
-
- if (additionalSpaceNeeded > 0)
- {
- (**errorDialogTemplate).boundsRect.bottom += additionalSpaceNeeded;
- errorTextItem->boundsRect.bottom += additionalSpaceNeeded;
- OffsetRect(&okButtonItem->boundsRect,0,additionalSpaceNeeded);
- }
-
- TextFont(oldFont);
- SetPort(oldPort);
-
- InitCursor();
- ParamText(errorString,nullStr,nullStr,nullStr);
-
- (void) StandardAlert(kErrorAlertID);
-
- ReleaseResource((Handle) errorDialogTemplate);
- ReleaseResource((Handle) errorDialogItems);
- }
-
-
- ///////////////////////////////////////////////////////////
- //
- // FatalErrorAlert
- //
- // A companion to ErrorAlert which also kills the process.
- //
-
- void
- FatalErrorAlert(short stringList,short whichString)
- {
- ErrorAlert(stringList,whichString);
- ExitToShell();
- }
-
-
- ///////////////////////////////////////////////////////////
- //
- // StandardDialogFilter and StandardDialogFilterYD
- //
- // These function takes care of routing events not meant
- // for the dialog window to other parts of the application.
- //
- // Use them as an alternative to passing a NIL ModalFilterProc
- // to ModalDialog() and CustomGet(Put)File. Unlike the default
- // filter, these routines properly processes update events
- // to keep background processes running.
- //
- // The Thread Manager, if present, is also called to yield
- // control to other cooperative threads within the process.
- //
- // Because of pascal calling conventions we need two separate
- // routines, but this is minimized by sharing implementation
- // in FilterProcCommon.
-
-
- ModalFilterUPP StandardDialogFilterUPP
- = NewModalFilterProc(StandardDialogFilterProc);
-
- ModalFilterYDUPP StandardDialogFilterYDUPP
- = NewModalFilterYDProc(StandardDialogFilterYDProc);
-
-
- pascal Boolean
- StandardDialogFilterProc(DialogRef theDialog, EventRecord* anEvent, short* itemHit)
- {
- // Call through common code to check for events we’d like to handle.
- // If that is unsuccessful, call through the System 7 StdFilterProc
- // to handle CR, “CMD-.” & ESC in an international-friendly manner.
-
- if (FilterProcCommon(theDialog, anEvent, itemHit))
- return true;
- else
- return (StdFilterProc(theDialog, anEvent, itemHit));
- }
-
-
- pascal Boolean
- StandardDialogFilterYDProc(DialogRef theDialog, EventRecord* anEvent, short* itemHit, void * /*unusedData*/)
- {
- // We don’t call through to StdFilterProc since the
- // Standard File Package already does everything we need.
-
- return FilterProcCommon(theDialog, anEvent, itemHit);
- }
-
-
- void
- PseudoClickInDialogItem(DialogRef theDialog, short itemToClick)
- {
- ControlRef itemHandle;
- Rect itemBox;
- long finalTicks;
- short itemType;
-
- GetDialogItem(theDialog,itemToClick,&itemType, (Handle *) &itemHandle,&itemBox);
-
- HiliteControl( itemHandle, kControlButtonPart );
- Delay(8,&finalTicks);
- HiliteControl( itemHandle, 0 );
- }
-
-
- Boolean
- ToggleCheckBox(DialogRef theDialog, short theCheckBox)
- {
- ControlRef itemHandle;
- Rect itemBox;
- short itemType;
-
- GetDialogItem(theDialog,theCheckBox,&itemType,(Handle *) &itemHandle,&itemBox);
-
- if (GetControlValue(itemHandle) == 1)
- {
- SetControlValue(itemHandle,0);
- return false;
- }
- else
- {
- SetControlValue(itemHandle,1);
- return true;
- }
- }
-
-
- Boolean
- FilterProcCommon(DialogRef theDialog, EventRecord * anEvent, short * /* itemHit */)
- {
- switch (anEvent->what)
- {
- case updateEvt:
- case activateEvt:
- // Update or activate for the dialog window?
- if (theDialog == (DialogRef) anEvent->message)
- break;
-
- // no, fall through to HandleEvent
-
- case diskEvt:
- HandleEvent(anEvent);
- return(false);
-
- default:
- break;
- }
-
- if (gHasThreadManager) // If we have threads, let them run!
- YieldToAnyThread();
-
- return false; // We didn’t handle the event
- }
-
-
- void SetDialogFontAndSize ( DialogRef theDialog, short fontNum, short fontSize ) {
- GrafPtr savePort;
- TEHandle teh = GetDialogTextEdit ( theDialog );
-
- GetPort ( &savePort );
- SetGrafPortOfDialog ( theDialog );
-
- // set up the port info
- TextFont ( fontNum );
- TextSize ( fontSize );
-
- // now deal with the static & edit text issues
- if ( teh != NULL ) {
- FontInfo f;
- TEPtr pText;
-
- GetFontInfo ( &f );
- pText = *teh;
- pText->txFont = applFont;
- pText->txSize = fontSize;
- pText->lineHeight = f.ascent + f.descent + f.leading;
- pText->fontAscent = f.ascent;
- }
-
- SetPort ( savePort );
- }
-